home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 April: Mac OS SDK / Dev.CD Apr 98 SDK1.toast / Development Kits (Disc 1) / Apple Game Sprockets / RAVE SDK 1.06 GM for MacOS / Example Projects / GameScene / GSRandomTriMesh.c < prev    next >
Encoding:
Text File  |  1996-03-21  |  13.4 KB  |  460 lines  |  [TEXT/MPS ]

  1. // ===========================================================================
  2. //
  3. //    GSRandomTriMesh.c
  4. //    
  5. //    Copyright (C) 1996 Apple Computer, Inc.  All rights reserved.
  6. //
  7. // ===========================================================================
  8.  
  9.  
  10. // ===========================================================================
  11. //    Includes
  12. // ===========================================================================
  13.  
  14. #include <stdlib.h>
  15. #include <stdio.h>
  16.  
  17. #include "RAVE.h"
  18.  
  19. #include "GSRandomTriMesh.h"
  20. #include "GSImage.h"
  21. #include "GSPicture.h"
  22. #include "GSColorTable.h"
  23. #include "GSDrawInfo.h"
  24. #include "GSUtilities.h"
  25. #include "GSError.h"
  26.  
  27.  
  28. // ===========================================================================
  29. //    Constants
  30. // ===========================================================================
  31.  
  32. #define                    kGSTriangleCount                    100
  33. #define                    kGSTexturePath                        "GS_RedLava.16.pict"
  34.  
  35.  
  36. // ===========================================================================
  37. //    Private Prototypes
  38. // ===========================================================================
  39.  
  40.     TGSError
  41. GSLoadTextureFromPath(
  42.     TGSDrawInfo*            inDrawInfo,
  43.     char*                    inPath,
  44.     TGSImage**                 outImage,
  45.     TQAColorTable**            outColorTable,
  46.     TQATexture**             outTexture);
  47.     
  48.     void 
  49. GSRandomVGouraud(
  50.     TGSDrawInfo*            inDrawInfo,
  51.     TQAVGouraud*            v);
  52.     
  53.     void 
  54. GSRandomVTexture(
  55.     TGSDrawInfo*            inDrawInfo,
  56.     TQAVTexture*            v);
  57.  
  58.  
  59. // ===========================================================================
  60. //    GSRandomTriMeshGouraud
  61. // ===========================================================================
  62.     TGSError
  63. GSRandomTriMeshGouraud(
  64.     TGSDrawInfo*        inDrawInfo)
  65. {
  66.     TQAIndexedTriangle*    triangles = nil;
  67.     TQAVGouraud*        vertices = nil;
  68.     TGSError            status = kGSError_None;
  69.     long                vertexCount = 2 * kGSTriangleCount;
  70.     long                i;
  71.  
  72.         // reset the random seed to 1.  if it's the same value every time
  73.         // this function is called, it'll be easier to debug.
  74.     srand(1);
  75.     
  76.         // allocate 2 vertices for every triangle we want to draw.
  77.         // this means that on average every triangle will be connected to at
  78.         // least one other.
  79.     vertices = malloc(vertexCount * sizeof(TQAVTexture));
  80.     
  81.     if (vertices == nil) {
  82.         status = kGSError_NotEnoughMemory;
  83.         goto cleanup;
  84.     }
  85.     
  86.         // allocate a single TQAIndexedTriangle for every triangle we
  87.         // wants draw.  these will hold the indexes into the vertices.
  88.     triangles = malloc(kGSTriangleCount * sizeof(TQAIndexedTriangle));
  89.     
  90.     if (triangles == nil) {
  91.         status = kGSError_NotEnoughMemory;
  92.         goto cleanup;
  93.     }
  94.     
  95.         // fill in the array of vertices with random values.  we have to fill
  96.         // in the uOverW and vOverW values before calling RandomVTexture because 
  97.         // that function assumes they've already been set.
  98.     for (i = 0; i < vertexCount; i++) {
  99.         GSRandomVGouraud(inDrawInfo, &vertices[i]);
  100.     } // endfor
  101.     
  102.         // fill in the default tri flags for each triangle, and calculate a 
  103.         // random index for each of the three vertex indexes.
  104.     for (i = 0; i < kGSTriangleCount; i++) {
  105.         triangles[i].triangleFlags = kQATriFlags_None;
  106.         
  107.         triangles[i].vertices[0] = 
  108.                 (long) (GSRandomFloat() * (vertexCount - 1));
  109.         triangles[i].vertices[1] = 
  110.                 (long) (GSRandomFloat() * (vertexCount - 1));
  111.         triangles[i].vertices[2] = 
  112.                 (long) (GSRandomFloat() * (vertexCount - 1));
  113.     } // endfor
  114.  
  115.     QARenderStart(inDrawInfo->mContext, nil, nil);
  116.  
  117.     QASubmitVerticesGouraud(inDrawInfo->mContext, vertexCount, vertices);
  118.         
  119.     QADrawTriMeshGouraud(inDrawInfo->mContext, kGSTriangleCount, triangles);
  120.         
  121.     QARenderEnd(inDrawInfo->mContext, nil);
  122.  
  123.     QASync(inDrawInfo->mContext);
  124.  
  125. cleanup:
  126.     if (vertices != nil) {
  127.         free(vertices);
  128.     }
  129.     
  130.     if (triangles != nil) {
  131.         free(triangles);
  132.     }
  133.     
  134.     return status;
  135. }
  136.  
  137.  
  138. // ===========================================================================
  139. //    GSRandomTriMeshTexture
  140. // ===========================================================================
  141.     TGSError
  142. GSRandomTriMeshTexture(
  143.     TGSDrawInfo*        inDrawInfo)
  144. {
  145.     TQAIndexedTriangle*    triangles = nil;
  146.     TQAVTexture*        vertices = nil;
  147.     TQATexture*            texture = nil;
  148.     TQAColorTable*        colorTable = nil;
  149.     TGSImage*            image = nil;
  150.     TGSError            gsError = kGSError_None;
  151.     TGSError            status = kGSError_None;
  152.     long                vertexCount = 2 * kGSTriangleCount;
  153.     long                i;
  154.  
  155.         // reset the random seed to 1.  if it's the same value every time
  156.         // this function is called, it'll be easier to debug.
  157.     srand(1);
  158.     
  159.         // load the texture from a file
  160.     gsError = GSLoadTextureFromPath(inDrawInfo, kGSTexturePath, &image,
  161.             &colorTable, &texture);
  162.             
  163.     if (gsError != kGSError_None) {
  164.         status = gsError;
  165.         goto cleanup;
  166.     }
  167.     
  168.         // set the current texture for this context to be the one we just loaded
  169.     QASetPtr(inDrawInfo->mContext, kQATag_Texture, texture);
  170.     
  171.         // allocate 2 vertices for every triangle we want to draw.
  172.         // this means that on average every triangle will be connected to at
  173.         // least one other.
  174.     vertices = malloc(vertexCount * sizeof(TQAVTexture));
  175.     
  176.     if (vertices == nil) {
  177.         status = kGSError_NotEnoughMemory;
  178.         goto cleanup;
  179.     }
  180.     
  181.         // allocate a single TQAIndexedTriangle for every triangle we
  182.         // wants draw.  these will hold the indexes into the vertices.
  183.     triangles = malloc(kGSTriangleCount * sizeof(TQAIndexedTriangle));
  184.     
  185.     if (triangles == nil) {
  186.         status = kGSError_NotEnoughMemory;
  187.         goto cleanup;
  188.     }
  189.     
  190.         // fill in the array of vertices with random values.  we have to fill
  191.         // in the uOverW and vOverW values before calling RandomVTexture because 
  192.         // that function assumes they've already been set.
  193.     for (i = 0; i < vertexCount; i++) {
  194.         vertices[i].uOverW = GSRandomFloat();
  195.         vertices[i].vOverW = GSRandomFloat();
  196.         
  197.         GSRandomVTexture(inDrawInfo, &vertices[i]);
  198.     } // endfor
  199.     
  200.         // fill in the default tri flags for each triangle, and calculate a 
  201.         // random index for each of the three vertex indexes.
  202.     for (i = 0; i < kGSTriangleCount; i++) {
  203.         triangles[i].triangleFlags = kQATriFlags_None;
  204.         
  205.         triangles[i].vertices[0] = 
  206.                 (long) (GSRandomFloat() * (vertexCount - 1));
  207.         triangles[i].vertices[1] = 
  208.                 (long) (GSRandomFloat() * (vertexCount - 1));
  209.         triangles[i].vertices[2] = 
  210.                 (long) (GSRandomFloat() * (vertexCount - 1));
  211.     } // endfor
  212.  
  213.     QARenderStart(inDrawInfo->mContext, nil, nil);
  214.  
  215.     QASubmitVerticesTexture(inDrawInfo->mContext, vertexCount, vertices);
  216.         
  217.     QADrawTriMeshTexture(inDrawInfo->mContext, kGSTriangleCount, triangles);
  218.         
  219.     QARenderEnd(inDrawInfo->mContext, nil);
  220.     
  221.     QASync(inDrawInfo->mContext);
  222.     
  223. cleanup:
  224.     if (vertices != nil) {
  225.         free(vertices);
  226.     }
  227.     
  228.     if (triangles != nil) {
  229.         free(triangles);
  230.     }
  231.     
  232.     if (image != nil) {
  233.         GSImage_Delete(image);
  234.     } 
  235.     
  236.     if (texture != nil) {
  237.         QATextureDelete(inDrawInfo->mEngine, texture);
  238.     }
  239.     
  240.     if (colorTable != nil) {
  241.         QAColorTableDelete(inDrawInfo->mEngine, colorTable);
  242.     }
  243.  
  244.     return status;
  245. }
  246.  
  247.  
  248. // ===========================================================================
  249. //    GSLoadTextureFromPath
  250. // ===========================================================================
  251.     TGSError
  252. GSLoadTextureFromPath(
  253.     TGSDrawInfo*            inDrawInfo,
  254.     char*                    inPath,
  255.     TGSImage**                 outImage,
  256.     TQAColorTable**            outColorTable,
  257.     TQATexture**             outTexture)
  258. {
  259.     TGSPicture*                picture = nil;
  260.     TQAError                qaError = kQANoErr;
  261.     TGSError                gsError = kGSError_None;
  262.     TGSError                status = kGSError_None;
  263.     
  264.         // set the pointers the caller passed to us to nil so we can tell
  265.         // if these objects were actually created or not
  266.     *outImage = nil;
  267.     *outColorTable = nil;
  268.     *outTexture = nil;
  269.     
  270.         // read the picture data from the file pointed to by the path into a
  271.         // TGSPicture.  this object handles any necessary conversion from 
  272.         // the format of the picture data in the file to the RAVE texture 
  273.         // format. the disposal of this picture will be handled by the
  274.         // TGSImage we create below.
  275.     gsError = GSPicture_NewFromPath(&picture, inDrawInfo->mTextureFormat, 
  276.             inPath);
  277.     
  278.     if (gsError != kGSError_None) {
  279.             // we couldn't find the picture file, so return the error.  we don't
  280.             // have to delete the GSPicture, because it deletes itself if an
  281.             // error occurs in the New call.
  282.         status = gsError;
  283.         goto failure;
  284.     }
  285.     
  286.         // create a TGSImage from the TGSPicture we just created above.  
  287.         // this object fills in the TQAImage structure with the appropriate
  288.         // values from the TGSPicture.  it will also optionally make every
  289.         // black pixel in the picture transparent and create mip maps for
  290.         // the texture.  it handles the disposal of the TGSPicture.  we use
  291.         // the TGSImage below to create an actual RAVE texture.
  292.     gsError = GSImage_NewFromPicture(outImage, picture, 
  293.             inDrawInfo->mTextureFormat, inDrawInfo->mTextureMakeBlackTransparent, 
  294.             inDrawInfo->mTextureMakeMipMap);
  295.     
  296.     if (gsError != kGSError_None) {
  297.             // for some reason we couldn't create a GSImage (probably not
  298.             // enough memory), so return the error.  GSImage also deletes when
  299.             // an error occurs in the New call.
  300.         status = gsError;
  301.         goto failure;
  302.     }
  303.     
  304.     if (inDrawInfo->mTextureMakeMipMap && !GSImage_IsValidMipMap(*outImage)) {
  305.             // the texture is supposed to be mipmapped, but GSImage couldn't
  306.             // mip map it for some reason
  307.         status = kGSError_RAVE;
  308.         goto failure;
  309.     }
  310.     
  311.         // try to create a texture for the engine, using the image data in
  312.         // our TGSImage object.  we'll return the texture to the caller in 
  313.         // outTexture.
  314.     qaError = QATextureNew(inDrawInfo->mEngine, inDrawInfo->mTextureFlags,
  315.             GSImage_GetPixelType(*outImage), 
  316.             GSImage_GetImages(*outImage),
  317.             outTexture);
  318.         
  319.     if (qaError != kQANoErr) {
  320.             // for some reason the engine couldn't create a texture (probably
  321.             // not enough memory), so return a RAVE error
  322.         status = kGSError_RAVE;
  323.         goto failure;
  324.     }
  325.     
  326.     if (inDrawInfo->mTextureFormat == kQAPixel_CL4 || 
  327.             inDrawInfo->mTextureFormat == kQAPixel_CL8) {
  328.         TGSColorTable*            colorTableP = GSImage_GetColorTable(*outImage);
  329.         GSAssert_(colorTableP);
  330.  
  331.             // create a new color table in the engine from the color table
  332.             // data in the TGSImage.  when a TGSPicture is created, it also
  333.             // creates a TGSColorTable, if necessary, which in turn stores 
  334.             // the color table from the picture file in an array of pixels
  335.             // in TQAImagePixelType format.  we can get the TGSColorTable
  336.             // out of the TGSImage by calling GSImage_GetColorTable.  
  337.             // 
  338.             // once the color table data has been used to create a 
  339.             // TQAColorTable, we can delete it.  in this case, however, it 
  340.             // won't be deleted until the TGSPicture which stores it is 
  341.             // itself deleted.
  342.         qaError = QAColorTableNew(inDrawInfo->mEngine, 
  343.                 GSColorTable_GetType(colorTableP), 
  344.                 GSColorTable_GetData(colorTableP),
  345.                 inDrawInfo->mTextureUseTransparentIndex, 
  346.                 outColorTable);
  347.                 
  348.         if (qaError != kQANoErr) {
  349.                 // we couldn't create a color table in this engine (perhaps
  350.                 // it doesn't support CL textures), so break out of the loop, 
  351.                 // since we can't continue if the engine can't create 
  352.                 // color tables.
  353.             status = kGSError_RAVE;
  354.             goto failure;
  355.         }
  356.  
  357.             // bind this color table to the texture.  
  358.         qaError = QATextureBindColorTable(inDrawInfo->mEngine,
  359.                 *outTexture, *outColorTable);
  360.         
  361.         if (qaError != kQANoErr) {
  362.                 // we couldn't bind this color table to the texture in 
  363.                 // this engine, so break out of the loop, since we won't 
  364.                 // be able to draw this texture
  365.             status = kGSError_RAVE;
  366.             goto failure;
  367.         }
  368.     }
  369.         
  370.     if (inDrawInfo->mTextureDetach) {
  371.             // try to detach the texture from the engine
  372.         qaError = QATextureDetach(inDrawInfo->mEngine, *outTexture);
  373.  
  374.             // if the texture was successfully detached, delete the image
  375.             // which stores the texture's pixmap, since the engine now
  376.             // has its own copy of that data.  if the texture couldn't be
  377.             // detached, don't do anything (i.e., hold on to the image).
  378.         if (qaError == kQANoErr) {
  379.             GSImage_Delete(*outImage);
  380.             *outImage = nil;
  381.         }
  382.     }
  383.     
  384.     return status;
  385.     
  386. failure:
  387.     if (*outImage != nil) {
  388.             // this will also delete picture
  389.         GSImage_Delete(*outImage);
  390.         *outImage = nil;
  391.     } else if (picture != nil) {
  392.             // the image was never created, so we have to delete the picture
  393.             // manually
  394.         GSPicture_Delete(picture);
  395.     }
  396.     
  397.     if (*outTexture != nil) {
  398.         QATextureDelete(inDrawInfo->mEngine, *outTexture);
  399.         *outTexture = nil;
  400.     }
  401.     
  402.     if (*outColorTable != nil) {
  403.         QAColorTableDelete(inDrawInfo->mEngine, *outColorTable);
  404.         *outTexture = nil;
  405.     }
  406.     
  407.     return status;
  408. }
  409.  
  410.  
  411. // ===========================================================================
  412. //    GSRandomVGouraud
  413. // ===========================================================================
  414.     void 
  415. GSRandomVGouraud(
  416.     TGSDrawInfo*            inDrawInfo,
  417.     TQAVGouraud*            v)
  418. {
  419.     v->x = GSRandomFloat() * (float) (inDrawInfo->mContextRect.right - inDrawInfo->mContextRect.left) - 0.1;
  420.     v->y = GSRandomFloat() * (float) (inDrawInfo->mContextRect.bottom - inDrawInfo->mContextRect.top) - 0.1;
  421.     v->z = GSRandomFloat();
  422.     v->invW = 1.0 / v->z;
  423.     
  424.     v->a = 1.0;
  425.     v->r = GSRandomFloat();
  426.     v->g = GSRandomFloat();
  427.     v->b = GSRandomFloat();
  428. }
  429.  
  430.  
  431. // ===========================================================================
  432. //    GSRandomVTexture
  433. // ===========================================================================
  434.     void 
  435. GSRandomVTexture(
  436.     TGSDrawInfo*            inDrawInfo,
  437.     TQAVTexture*            v)
  438. {
  439.     v->x = GSRandomFloat() * (float) (inDrawInfo->mContextRect.right - inDrawInfo->mContextRect.left) - 0.1;
  440.     v->y = GSRandomFloat() * (float) (inDrawInfo->mContextRect.bottom - inDrawInfo->mContextRect.top) - 0.1;
  441.     v->z = GSRandomFloat();
  442.     v->invW = 1.0 / v->z;
  443.     
  444.     v->uOverW *= v->invW;
  445.     v->vOverW *= v->invW;
  446.     
  447.     v->a = 1.0;
  448.     v->r = GSRandomFloat();
  449.     v->g = GSRandomFloat();
  450.     v->b = GSRandomFloat();
  451.     
  452.     v->kd_r = 1.0;
  453.     v->kd_g = 1.0;
  454.     v->kd_b = 1.0;
  455.     
  456.     v->ks_r = 0.0;
  457.     v->ks_g = 0.0;
  458.     v->ks_b = 0.0;
  459. }
  460.